package com.xjrsoft.common.serializers;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
import com.xjrsoft.core.tool.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;

public class XjrNumberSerializer extends StdScalarSerializer<Number> implements ContextualSerializer {

    protected DecimalFormat _formatter;

    public XjrNumberSerializer() {
        this((DecimalFormat)null);
    }

    public XjrNumberSerializer(DecimalFormat formatter) {
        super(Number.class);
        this._formatter = formatter;
    }

    protected XjrNumberSerializer(Class<Number> t) {
        this((DecimalFormat)null);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        JsonFormat.Value format = this.findFormatOverrides(prov, property, this.handledType());
        if (format != null && StringUtils.isNotEmpty(format.getPattern())) {
            DecimalFormat formatter = new DecimalFormat(format.getPattern());
            return new XjrNumberSerializer(formatter);
        }
        return this;
    }

    @Override
    public void serialize(Number value, JsonGenerator g, SerializerProvider serializerProvider) throws IOException {
        if (this._formatter != null) {
            g.writeString(this._formatter.format(value));
        } else if (value instanceof BigDecimal) {
            g.writeNumber((BigDecimal)value);
        } else if (value instanceof BigInteger) {
            g.writeNumber((BigInteger)value);
        } else if (value instanceof Long) {
            g.writeNumber(value.longValue());
        } else if (value instanceof Double) {
            g.writeNumber(value.doubleValue());
        } else if (value instanceof Float) {
            g.writeNumber(value.floatValue());
        } else if (!(value instanceof Integer) && !(value instanceof Byte) && !(value instanceof Short)) {
            g.writeNumber(value.toString());
        } else {
            g.writeNumber(value.intValue());
        }
    }
}
